using System;
using System.Collections.Generic;
using System.Linq;
using Synapse.Framework.IoC.Option;

namespace Synapse.Framework.IoC.Bind
{
    public class Binder : IBinder, IBinding
    {
       public Type Contract { get; private set; }
       public IList<Implemetation> Implementations { get; private set; }

        public Binder(Type contract)
        {
            Contract = contract;
            Implementations = new List<Implemetation>();
        }

        public IOptions To(Type implementation)
        {
            return CreateOptions(implementation, null);
        }

        public IOptions To(object instance)
        {
            return CreateOptions(instance.GetType(), instance);
        }

        private IOptions CreateOptions(Type type, object instance)
        {
            var currentImplemetation = Implementations.SingleOrDefault(i => i.Type == type);
            if (currentImplemetation==null)
            {
                currentImplemetation = new Implemetation(type)
                {
                    Default = !Implementations.Any(),
                    Instance = instance
                };
                Implementations.Add(currentImplemetation);
            }
            return new Options(Implementations, currentImplemetation);
        }
    }

    public class Binder<I> : IBinding, IBinder<I>
    {
        private readonly Binder inner;

        public Type Contract { get {return inner.Contract;}}
        public IList<Implemetation> Implementations { get { return inner.Implementations; } }

        public Binder(Binder inner)
        {
            this.inner = inner;
        }

        public IOptions To<T>() where T:class,I
        {
            return inner.To(typeof(T));
        }

        public IOptions To<T>(T instance) where T : class, I
        {
            return inner.To(instance);
        }
    }
}